/**
 * @file camera_capture_mode.c
 * @brief 实现专门用于获取摄像头图像的模式
 * @version 1.0
 * @date 2025-04-25
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <curl/curl.h>
#include <unistd.h>

#include "camera_capture_mode.h"
#include "system_utils.h"
#include "camera_time_sync.h"
#include "thread_utils.h"

// 修改自camera_test中的代码，适应当前项目需求
// 全局配置
static struct {
    // 摄像头配置
    CameraCaptureConfig cam400w;
    CameraCaptureConfig cam800w_left;
    CameraCaptureConfig cam800w_right;
    
    // 状态标志
    bool initialized;
    bool running;
    
    // 统计信息
    int total_captures;
    int successful_captures;
} g_camera_capture = {0};

// 内存写入数据结构
typedef struct {
    char *memory;
    size_t size;
} MemoryStruct;

// 函数前向声明
static int capture_camera_image(const CameraCaptureConfig *config);
static void get_time_string(char *buffer, size_t size);
static int is_valid_jpeg(unsigned char *data, size_t size);
static int try_camera_url(const CameraCaptureConfig *config, const char *url, const char *filepath);

/**
 * @brief 内存写入回调函数，用于curl
 * 
 * @param contents 收到的数据
 * @param size 数据块大小
 * @param nmemb 数据块数量
 * @param userp 用户数据（MemoryStruct指针）
 * @return size_t 实际处理的数据大小
 */
static size_t capture_write_memory_callback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    MemoryStruct *mem = (MemoryStruct *)userp;
    
    char *ptr = realloc(mem->memory, mem->size + realsize + 1);
    if (ptr == NULL) {
        log_message(LOG_LEVEL_ERROR, "内存不足 (大小: %zu 字节)", mem->size + realsize + 1);
        return 0;
    }
    
    mem->memory = ptr;
    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;  // 确保字符串以null结尾
    
    return realsize;
}

/**
 * @brief 初始化摄像头捕获模式
 * 
 * @return int 成功返回0，失败返回非0
 */
int init_camera_capture_mode(void) {
    if (g_camera_capture.initialized) {
        log_message(LOG_LEVEL_INFO, "摄像头捕获模式: 已初始化");
        return 0;
    }
    
    // 初始化摄像头配置
    // 400W摄像头
    snprintf(g_camera_capture.cam400w.ip, sizeof(g_camera_capture.cam400w.ip), "%s", "192.168.1.60");
    snprintf(g_camera_capture.cam400w.username, sizeof(g_camera_capture.cam400w.username), "%s", "admin");
    snprintf(g_camera_capture.cam400w.password, sizeof(g_camera_capture.cam400w.password), "%s", "hitmc401");
    snprintf(g_camera_capture.cam400w.save_dir, sizeof(g_camera_capture.cam400w.save_dir), "%s", "picture_docu");
    snprintf(g_camera_capture.cam400w.prefix, sizeof(g_camera_capture.cam400w.prefix), "%s", "cam400w");
    g_camera_capture.cam400w.capture_interval_ms = 3000;
    g_camera_capture.cam400w.max_captures = -1;  // 无限捕获
    
    // 左800W摄像头
    snprintf(g_camera_capture.cam800w_left.ip, sizeof(g_camera_capture.cam800w_left.ip), "%s", "192.168.1.64");
    snprintf(g_camera_capture.cam800w_left.username, sizeof(g_camera_capture.cam800w_left.username), "%s", "admin");
    snprintf(g_camera_capture.cam800w_left.password, sizeof(g_camera_capture.cam800w_left.password), "%s", "hitmc401");
    snprintf(g_camera_capture.cam800w_left.save_dir, sizeof(g_camera_capture.cam800w_left.save_dir), "%s", "picture_docu");
    snprintf(g_camera_capture.cam800w_left.prefix, sizeof(g_camera_capture.cam800w_left.prefix), "%s", "cam800w_left");
    g_camera_capture.cam800w_left.capture_interval_ms = 3000;
    g_camera_capture.cam800w_left.max_captures = -1;  // 无限捕获
    
    // 右800W摄像头
    snprintf(g_camera_capture.cam800w_right.ip, sizeof(g_camera_capture.cam800w_right.ip), "%s", "192.168.1.65");
    snprintf(g_camera_capture.cam800w_right.username, sizeof(g_camera_capture.cam800w_right.username), "%s", "admin");
    snprintf(g_camera_capture.cam800w_right.password, sizeof(g_camera_capture.cam800w_right.password), "%s", "hitmc401");
    snprintf(g_camera_capture.cam800w_right.save_dir, sizeof(g_camera_capture.cam800w_right.save_dir), "%s", "picture_docu");
    snprintf(g_camera_capture.cam800w_right.prefix, sizeof(g_camera_capture.cam800w_right.prefix), "%s", "cam800w_right");
    g_camera_capture.cam800w_right.capture_interval_ms = 3000;
    g_camera_capture.cam800w_right.max_captures = -1;  // 无限捕获
    
    // 创建保存目录
    if (create_directory("picture_docu") != 0) {
        log_message(LOG_LEVEL_ERROR, "摄像头捕获模式: 创建保存目录失败");
        return -1;
    }
    
    // 初始化curl库
    CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
    if (code != CURLE_OK) {
        log_message(LOG_LEVEL_ERROR, "摄像头捕获模式: 初始化curl库失败: %s", curl_easy_strerror(code));
        return -1;
    }
    
    // 初始化状态
    g_camera_capture.initialized = true;
    g_camera_capture.running = false;
    g_camera_capture.total_captures = 0;
    g_camera_capture.successful_captures = 0;
    
    log_message(LOG_LEVEL_INFO, "摄像头捕获模式: 初始化成功");
    return 0;
}

/**
 * @brief 启动摄像头捕获模式
 * 
 * @param capture_count 捕获图像的次数，0表示只设置时间不捕获，-1表示无限捕获直到程序停止
 * @return int 成功返回0，失败返回非0
 */
int run_camera_capture_mode(int capture_count) {
    if (!g_camera_capture.initialized) {
        log_message(LOG_LEVEL_ERROR, "摄像头捕获模式: 尚未初始化");
        return -1;
    }
    
    if (g_camera_capture.running) {
        log_message(LOG_LEVEL_ERROR, "摄像头捕获模式: 已经在运行");
        return -1;
    }
    
    g_camera_capture.running = true;
    
    // 同步摄像头时间
    log_message(LOG_LEVEL_INFO, "摄像头捕获模式: 开始同步摄像头时间...");
    
    // 创建临时摄像头授权信息用于同步时间
    CameraAuthInfo cam400w_auth = {0};
    CameraAuthInfo cam800w_left_auth = {0};
    CameraAuthInfo cam800w_right_auth = {0};
    
    // 设置400W摄像头认证信息
    snprintf(cam400w_auth.ip, sizeof(cam400w_auth.ip), "%s", g_camera_capture.cam400w.ip);
    snprintf(cam400w_auth.username, sizeof(cam400w_auth.username), "%s", g_camera_capture.cam400w.username);
    snprintf(cam400w_auth.password, sizeof(cam400w_auth.password), "%s", g_camera_capture.cam400w.password);
    cam400w_auth.type = CAMERA_TYPE_400W;
    
    // 设置左800W摄像头认证信息
    snprintf(cam800w_left_auth.ip, sizeof(cam800w_left_auth.ip), "%s", g_camera_capture.cam800w_left.ip);
    snprintf(cam800w_left_auth.username, sizeof(cam800w_left_auth.username), "%s", g_camera_capture.cam800w_left.username);
    snprintf(cam800w_left_auth.password, sizeof(cam800w_left_auth.password), "%s", g_camera_capture.cam800w_left.password);
    cam800w_left_auth.type = CAMERA_TYPE_800W;
    
    // 设置右800W摄像头认证信息
    snprintf(cam800w_right_auth.ip, sizeof(cam800w_right_auth.ip), "%s", g_camera_capture.cam800w_right.ip);
    snprintf(cam800w_right_auth.username, sizeof(cam800w_right_auth.username), "%s", g_camera_capture.cam800w_right.username);
    snprintf(cam800w_right_auth.password, sizeof(cam800w_right_auth.password), "%s", g_camera_capture.cam800w_right.password);
    cam800w_right_auth.type = CAMERA_TYPE_800W;
    
    // 同步摄像头时间
    log_message(LOG_LEVEL_INFO, "同步400W摄像头(%s)时间...", cam400w_auth.ip);
    if (sync_camera_time(&cam400w_auth) != 0) {
        log_message(LOG_LEVEL_ERROR, "400W摄像头时间同步失败");
    }
    
    log_message(LOG_LEVEL_INFO, "同步左800W摄像头(%s)时间...", cam800w_left_auth.ip);
    if (sync_camera_time(&cam800w_left_auth) != 0) {
        log_message(LOG_LEVEL_ERROR, "左800W摄像头时间同步失败");
    }
    
    log_message(LOG_LEVEL_INFO, "同步右800W摄像头(%s)时间...", cam800w_right_auth.ip);
    if (sync_camera_time(&cam800w_right_auth) != 0) {
        log_message(LOG_LEVEL_ERROR, "右800W摄像头时间同步失败");
    }
    
    // 如果只需要设置时间，不捕获图像
    if (capture_count == 0) {
        g_camera_capture.running = false;
        log_message(LOG_LEVEL_INFO, "摄像头捕获模式: 时间同步完成，不需要捕获图像");
        return 0;
    }
    
    // 开始捕获图像循环
    log_message(LOG_LEVEL_INFO, "摄像头捕获模式: 开始捕获图像，计划捕获次数: %d", 
               capture_count < 0 ? 0 : capture_count);
    
    int count = 0;
    while (g_camera_capture.running && (capture_count < 0 || count < capture_count)) {
        log_message(LOG_LEVEL_INFO, "摄像头捕获模式: 开始第 %d 次捕获", count + 1);
        
        // 捕获所有3个摄像头的图像
        int success = 0;
        
        // 捕获400W摄像头图像
        if (capture_camera_image(&g_camera_capture.cam400w) == 0) {
            success++;
        }
        
        // 捕获左800W摄像头图像
        if (capture_camera_image(&g_camera_capture.cam800w_left) == 0) {
            success++;
        }
        
        // 捕获右800W摄像头图像
        if (capture_camera_image(&g_camera_capture.cam800w_right) == 0) {
            success++;
        }
        
        // 更新统计信息
        g_camera_capture.total_captures++;
        if (success == 3) {
            g_camera_capture.successful_captures++;
        }
        
        count++;
        
        // 如果已达到捕获次数，退出循环
        if (capture_count > 0 && count >= capture_count) {
            break;
        }
        
        // 等待指定的间隔时间
        int interval = g_camera_capture.cam400w.capture_interval_ms;
        log_message(LOG_LEVEL_INFO, "摄像头捕获模式: 等待 %d 毫秒进行下一次捕获", interval);
        thread_sleep(interval);
    }
    
    g_camera_capture.running = false;
    log_message(LOG_LEVEL_INFO, "摄像头捕获模式: 完成图像捕获，总计: %d，成功: %d", 
               g_camera_capture.total_captures, g_camera_capture.successful_captures);
    
    return 0;
}

/**
 * @brief 清理摄像头捕获模式资源
 */
void cleanup_camera_capture_mode(void) {
    if (!g_camera_capture.initialized) {
        return;
    }
    
    // 停止运行
    g_camera_capture.running = false;
    
    // 清理curl库
    curl_global_cleanup();
    
    // 重置状态
    g_camera_capture.initialized = false;
    
    log_message(LOG_LEVEL_INFO, "摄像头捕获模式: 资源已清理");
}

// 获取当前时间的字符串表示
static void get_time_string(char *buffer, size_t size) {
    time_t now = time(NULL);
    struct tm *t = localtime(&now);
    strftime(buffer, size, "%Y%m%d_%H%M%S", t);
}

// 检查数据是否是有效的JPEG
static int is_valid_jpeg(unsigned char *data, size_t size) {
    // 对于非常小的数据包，可能不是图像
    if (size < 100) return 0;
    
    // JPEG文件应以0xFF 0xD8开始
    if (data[0] == 0xFF && data[1] == 0xD8) {
        return 1;
    }
    
    return 0;
}

// 捕获摄像头图像
static int capture_camera_image(const CameraCaptureConfig *config) {
    char filepath[512];
    char time_str[32];
    int ret = -1;
    
    // 获取当前时间字符串
    get_time_string(time_str, sizeof(time_str));
    
    // 构建保存文件的完整路径
    snprintf(filepath, sizeof(filepath), "%s/%s_%s.jpg", 
             config->save_dir, config->prefix, time_str);
    
    // 确保目录存在
    if (create_directory(config->save_dir) != 0) {
        log_message(LOG_LEVEL_ERROR, "创建目录失败: %s", config->save_dir);
        return -1;
    }
    
    // 构造URL
    char url[256];
    
    // 根据IP地址选择不同的URL
    if (strcmp(config->ip, "192.168.1.60") == 0) {
        // 400W摄像头使用特定URL
        snprintf(url, sizeof(url), "http://%s/ISAPI/Streaming/channels/102/picture", config->ip);
    } else {
        // 800W摄像头使用标准URL
        snprintf(url, sizeof(url), "http://%s/ISAPI/Streaming/channels/1/picture", config->ip);
    }
    
    // 尝试获取图像
    ret = try_camera_url(config, url, filepath);
    
    return ret;
}

// 尝试从指定URL获取图像
static int try_camera_url(const CameraCaptureConfig *config, const char *url, const char *filepath) {
    CURL *curl;
    CURLcode res;
    int ret = -1;
    
    // 使用内存缓冲区接收数据
    MemoryStruct chunk;
    
    chunk.memory = malloc(1);  // 为了realloc
    chunk.size = 0;    // 当前没有数据
    
    // 初始化libcurl
    curl = curl_easy_init();
    if (curl) {
        // 设置URL
        curl_easy_setopt(curl, CURLOPT_URL, url);
        
        // 设置用户名和密码，使用摘要认证
        curl_easy_setopt(curl, CURLOPT_USERNAME, config->username);
        curl_easy_setopt(curl, CURLOPT_PASSWORD, config->password);
        curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
        
        // 设置写入数据回调到内存
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, capture_write_memory_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
        
        // 设置超时
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);
        
        // 执行请求
        res = curl_easy_perform(curl);
        
        // 检查请求是否成功
        if(res != CURLE_OK) {
            log_message(LOG_LEVEL_ERROR, "获取图像失败 %s: %s", url, curl_easy_strerror(res));
            ret = -1;
        } else {
            // 验证获取到的数据是否是有效的JPEG
            if (chunk.size > 0 && is_valid_jpeg((unsigned char*)chunk.memory, chunk.size)) {
                // 写入文件
                FILE *fp = fopen(filepath, "wb");
                if (fp) {
                    if (fwrite(chunk.memory, 1, chunk.size, fp) == chunk.size) {
                        // 成功保存图像
                        log_message(LOG_LEVEL_INFO, "成功保存: %s (大小: %zu 字节)", filepath, chunk.size);
                        
                        // 设置文件权限为777
                        #ifdef __linux__
                            if (chmod(filepath, 0777) != 0) {
                                log_message(LOG_LEVEL_WARNING, "无法修改文件权限: %s", filepath);
                            }
                        #endif
                        ret = 0;
                    } else {
                        log_message(LOG_LEVEL_ERROR, "写入文件失败: %s", filepath);
                    }
                    fclose(fp);
                } else {
                    log_message(LOG_LEVEL_ERROR, "无法创建文件: %s", filepath);
                }
            } else {
                log_message(LOG_LEVEL_ERROR, "收到无效的JPEG数据: %s (大小: %zu 字节)", url, chunk.size);
            }
        }
        
        // 清理curl
        curl_easy_cleanup(curl);
    } else {
        log_message(LOG_LEVEL_ERROR, "初始化curl会话失败");
    }
    
    // 释放内存
    free(chunk.memory);
    
    return ret;
} 